package igor.lakienko.ru.generation.quotes.service;

import igor.lakienko.ru.generation.quotes.dto.CurrencyDto;
import igor.lakienko.ru.generation.quotes.dto.MessageEventDto;
import igor.lakienko.ru.generation.quotes.entity.CurrencyEntity;
import igor.lakienko.ru.generation.quotes.enums.Currency;
import igor.lakienko.ru.generation.quotes.enums.RecommendationAnalysts;
import igor.lakienko.ru.generation.quotes.mapper.CurrencyMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.ThreadLocalRandom;

/**
 * Сервис для работы с валютой.
 */
@Service
@RequiredArgsConstructor
public class CurrencyService {

    private final CurrencyMapper currencyMapper;

    @Value("${quote.responseSleepInMillis}")
    long responseSleepInMillis;

    @Value("${quote.quoteSizeBatch}")
    long currencySizeBatch;

    /**
     * Постоянное получение валюты с задержкой указанной в параметрах.
     */
    public MessageEventDto getCurrency() {
        try {
            Thread.sleep(responseSleepInMillis);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        CurrencyEntity randomCurrency = getRandomCurrency();
        return currencyMapper.currencyEntityToDto(randomCurrency);
    }

    /**
     * Получения списка валюты в размере указанном в конфигурационном файле.
     */
    public Collection<CurrencyDto> getCurrencies() {
        ArrayList<CurrencyEntity> currenciesEntity = new ArrayList<>();
        for (int i = 0; i < currencySizeBatch; i++) {
            CurrencyEntity randomCurrency = getRandomCurrency();
            currenciesEntity.add(randomCurrency);
        }
        return currencyMapper.currenciesEntityToDto(currenciesEntity);
    }

    /**
     * Получения случайного металла из списка, со случайными параметрами.
     */
    private CurrencyEntity getRandomCurrency() {
        Currency[] currencies = Currency.values();
        int randomCurrency = ThreadLocalRandom.current().nextInt(currencies.length);
        Currency currency = currencies[randomCurrency];
        float price = currency.getPrice();
        BigDecimal bid = BigDecimal.valueOf(price + ThreadLocalRandom.current()
                .nextDouble(1.0D, 10.0D)).setScale(2, RoundingMode.HALF_DOWN);
        BigDecimal offer = BigDecimal.valueOf(price - ThreadLocalRandom.current()
                .nextDouble(1.0D, 10.0D)).setScale(2, RoundingMode.HALF_DOWN);
        float yearlyVolatility = BigDecimal.valueOf(ThreadLocalRandom.current().nextDouble(-7.0F, 15.0F))
                .setScale(2, RoundingMode.HALF_DOWN).floatValue();
        BigInteger currencyVolume = BigInteger.valueOf(ThreadLocalRandom.current()
                .nextLong(10, 10_000_000));

        return CurrencyEntity.builder()
                .currency(currency)
                .fullCurrencyName(currency.getDescription())
                .bid(bid)
                .offer(offer)
                .price(price)
                .currencyVolume(currencyVolume)
                .recommendationAnalysts(getRecommendationAnalysts())
                .yearlyVolatility(yearlyVolatility)
                .build();
    }

    private String getRecommendationAnalysts() {
        RecommendationAnalysts[] recommendationAnalysts = RecommendationAnalysts.values();
        int randomStocks = ThreadLocalRandom.current().nextInt(recommendationAnalysts.length);
        RecommendationAnalysts recommendation = recommendationAnalysts[randomStocks];
        return recommendation.getRecommendation();
    }

}
